#[cfg(test)]
mod tests {
    use crate::{LoggingConfig, LogFormat, LogOutput, init_logging};
    use std::sync::Once;

    static INIT: Once = Once::new();

    fn setup_test_env() {
        INIT.call_once(|| {
            // 确保测试环境干净，只初始化一次
            std::env::remove_var("RUST_LOG");
            // 只调用一次init_logging避免冲突
            let config = LoggingConfig::default();
            init_logging(&config);
        });
    }

    #[test]
    fn test_logging_config_default() {
        let config = LoggingConfig::default();
        assert_eq!(config.level, "info");
        assert!(matches!(config.format, LogFormat::Json));
        assert!(matches!(config.output, LogOutput::Console));
        assert!(config.file_path.is_none());
        assert!(config.console_output);
    }

    #[test]
    fn test_logging_config_creation() {
        let config = LoggingConfig {
            level: "debug".to_string(),
            format: LogFormat::Plain,
            output: LogOutput::File,
            file_path: Some("/var/log/app.log".to_string()),
            console_output: false,
        };

        assert_eq!(config.level, "debug");
        assert!(matches!(config.format, LogFormat::Plain));
        assert!(matches!(config.output, LogOutput::File));
        assert_eq!(config.file_path, Some("/var/log/app.log".to_string()));
        assert!(!config.console_output);
    }

    #[test]
    fn test_log_format_serialization() {
        // Test JSON format
        let json_format = LogFormat::Json;
        let serialized = serde_json::to_string(&json_format).unwrap();
        assert_eq!(serialized, "\"json\"");
        
        let deserialized: LogFormat = serde_json::from_str(&serialized).unwrap();
        assert!(matches!(deserialized, LogFormat::Json));

        // Test Plain format
        let plain_format = LogFormat::Plain;
        let serialized = serde_json::to_string(&plain_format).unwrap();
        assert_eq!(serialized, "\"plain\"");
        
        let deserialized: LogFormat = serde_json::from_str(&serialized).unwrap();
        assert!(matches!(deserialized, LogFormat::Plain));
    }

    #[test]
    fn test_log_output_serialization() {
        // Test Console output
        let console_output = LogOutput::Console;
        let serialized = serde_json::to_string(&console_output).unwrap();
        assert_eq!(serialized, "\"console\"");
        
        let deserialized: LogOutput = serde_json::from_str(&serialized).unwrap();
        assert!(matches!(deserialized, LogOutput::Console));

        // Test File output
        let file_output = LogOutput::File;
        let serialized = serde_json::to_string(&file_output).unwrap();
        assert_eq!(serialized, "\"file\"");
        
        let deserialized: LogOutput = serde_json::from_str(&serialized).unwrap();
        assert!(matches!(deserialized, LogOutput::File));

        // Test Both output
        let both_output = LogOutput::Both;
        let serialized = serde_json::to_string(&both_output).unwrap();
        assert_eq!(serialized, "\"both\"");
        
        let deserialized: LogOutput = serde_json::from_str(&serialized).unwrap();
        assert!(matches!(deserialized, LogOutput::Both));
    }

    #[test]
    fn test_logging_config_serialization() {
        let config = LoggingConfig {
            level: "warn".to_string(),
            format: LogFormat::Plain,
            output: LogOutput::Both,
            file_path: Some("app.log".to_string()),
            console_output: true,
        };

        // Test serialization
        let serialized = serde_json::to_string(&config).unwrap();
        assert!(serialized.contains("\"level\":\"warn\""));
        assert!(serialized.contains("\"format\":\"plain\""));
        assert!(serialized.contains("\"output\":\"both\""));
        assert!(serialized.contains("\"file_path\":\"app.log\""));
        assert!(serialized.contains("\"console_output\":true"));

        // Test deserialization
        let deserialized: LoggingConfig = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized.level, "warn");
        assert!(matches!(deserialized.format, LogFormat::Plain));
        assert!(matches!(deserialized.output, LogOutput::Both));
        assert_eq!(deserialized.file_path, Some("app.log".to_string()));
        assert!(deserialized.console_output);
    }

    #[test]
    fn test_logging_config_toml_serialization() {
        let config = LoggingConfig {
            level: "error".to_string(),
            format: LogFormat::Json,
            output: LogOutput::File,
            file_path: Some("error.log".to_string()),
            console_output: false,
        };

        // Test TOML serialization
        let toml_str = toml::to_string(&config).unwrap();
        assert!(toml_str.contains("level = \"error\""));
        assert!(toml_str.contains("format = \"json\""));
        assert!(toml_str.contains("output = \"file\""));
        assert!(toml_str.contains("file_path = \"error.log\""));
        assert!(toml_str.contains("console_output = false"));

        // Test TOML deserialization
        let deserialized: LoggingConfig = toml::from_str(&toml_str).unwrap();
        assert_eq!(deserialized.level, "error");
        assert!(matches!(deserialized.format, LogFormat::Json));
        assert!(matches!(deserialized.output, LogOutput::File));
        assert_eq!(deserialized.file_path, Some("error.log".to_string()));
        assert!(!deserialized.console_output);
    }

    #[test]
    fn test_init_logging_with_different_levels() {
        setup_test_env();

        // 由于全局subscriber只能设置一次，这里只测试配置创建而不调用init_logging
        let config = LoggingConfig {
            level: "trace".to_string(),
            format: LogFormat::Plain,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        assert_eq!(config.level, "trace");

        let config = LoggingConfig {
            level: "debug".to_string(),
            format: LogFormat::Json,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        assert_eq!(config.level, "debug");
    }

    #[test]
    fn test_init_logging_with_invalid_level() {
        setup_test_env();

        // Test with invalid level - should not panic, just test config creation
        let config = LoggingConfig {
            level: "invalid".to_string(),
            format: LogFormat::Plain,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        
        // This should not panic, just verify config is created
        assert_eq!(config.level, "invalid");
    }

    #[test]
    fn test_init_logging_with_different_formats() {
        setup_test_env();

        // Test JSON format config creation
        let config = LoggingConfig {
            level: "info".to_string(),
            format: LogFormat::Json,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        assert!(matches!(config.format, LogFormat::Json));

        // Test Plain format config creation
        let config = LoggingConfig {
            level: "info".to_string(),
            format: LogFormat::Plain,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        assert!(matches!(config.format, LogFormat::Plain));
    }

    #[test]
    fn test_init_logging_with_file_output() {
        setup_test_env();

        // Test file output config creation
        let config = LoggingConfig {
            level: "info".to_string(),
            format: LogFormat::Json,
            output: LogOutput::File,
            file_path: Some("test.log".to_string()),
            console_output: false,
        };
        assert!(matches!(config.output, LogOutput::File));
        assert_eq!(config.file_path, Some("test.log".to_string()));

        // Test both output config creation
        let config = LoggingConfig {
            level: "debug".to_string(),
            format: LogFormat::Plain,
            output: LogOutput::Both,
            file_path: Some("test_both.log".to_string()),
            console_output: true,
        };
        assert!(matches!(config.output, LogOutput::Both));
    }

    #[test]
    fn test_logging_config_clone() {
        let config = LoggingConfig {
            level: "debug".to_string(),
            format: LogFormat::Json,
            output: LogOutput::File,
            file_path: Some("clone_test.log".to_string()),
            console_output: true,
        };

        let cloned_config = config.clone();
        assert_eq!(config.level, cloned_config.level);
        assert!(matches!(cloned_config.format, LogFormat::Json));
        assert!(matches!(cloned_config.output, LogOutput::File));
        assert_eq!(config.file_path, cloned_config.file_path);
        assert_eq!(config.console_output, cloned_config.console_output);
    }

    #[test]
    fn test_logging_config_debug() {
        let config = LoggingConfig::default();
        let debug_str = format!("{:?}", config);
        assert!(debug_str.contains("LoggingConfig"));
        assert!(debug_str.contains("level"));
        assert!(debug_str.contains("format"));
        assert!(debug_str.contains("output"));
    }

    #[test]
    fn test_log_format_debug() {
        let json_format = LogFormat::Json;
        let plain_format = LogFormat::Plain;
        
        let json_debug = format!("{:?}", json_format);
        let plain_debug = format!("{:?}", plain_format);
        
        assert!(json_debug.contains("Json"));
        assert!(plain_debug.contains("Plain"));
    }

    #[test]
    fn test_log_output_debug() {
        let console_output = LogOutput::Console;
        let file_output = LogOutput::File;
        let both_output = LogOutput::Both;
        
        let console_debug = format!("{:?}", console_output);
        let file_debug = format!("{:?}", file_output);
        let both_debug = format!("{:?}", both_output);
        
        assert!(console_debug.contains("Console"));
        assert!(file_debug.contains("File"));
        assert!(both_debug.contains("Both"));
    }

    #[test]
    fn test_logging_config_with_empty_level() {
        let config = LoggingConfig {
            level: "".to_string(),
            format: LogFormat::Plain,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        
        // Should not panic, just verify config is created with empty level
        assert_eq!(config.level, "");
    }

    #[test]
    fn test_logging_config_case_sensitivity() {
        setup_test_env();

        // Test uppercase level config creation
        let config = LoggingConfig {
            level: "DEBUG".to_string(),
            format: LogFormat::Json,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        assert_eq!(config.level, "DEBUG");

        // Test mixed case level config creation
        let config = LoggingConfig {
            level: "Info".to_string(),
            format: LogFormat::Plain,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        assert_eq!(config.level, "Info");
    }

    #[test]
    fn test_logging_config_partial_deserialization() {
        // Test with minimal JSON (missing optional fields)
        let minimal_json = r#"{"level": "warn", "format": "plain", "output": "console", "console_output": true}"#;
        let config: LoggingConfig = serde_json::from_str(minimal_json).unwrap();
        
        assert_eq!(config.level, "warn");
        assert!(matches!(config.format, LogFormat::Plain));
        assert!(matches!(config.output, LogOutput::Console));
        assert!(config.file_path.is_none());
        assert!(config.console_output);
    }

    #[test]
    fn test_logging_config_with_file_path_validation() {
        // Test with file output but no file path
        let config = LoggingConfig {
            level: "info".to_string(),
            format: LogFormat::Json,
            output: LogOutput::File,
            file_path: None,
            console_output: false,
        };
        
        // This should still work (config creation)
        assert!(matches!(config.output, LogOutput::File));
        assert!(config.file_path.is_none());

        // Test with file output and valid file path
        let config = LoggingConfig {
            level: "info".to_string(),
            format: LogFormat::Json,
            output: LogOutput::File,
            file_path: Some("valid.log".to_string()),
            console_output: false,
        };
        
        assert_eq!(config.file_path, Some("valid.log".to_string()));
    }

    #[test]
    fn test_multiple_init_logging_calls() {
        setup_test_env();

        // Multiple config creations should not panic
        let config1 = LoggingConfig::default();
        assert_eq!(config1.level, "info");

        let config2 = LoggingConfig {
            level: "debug".to_string(),
            format: LogFormat::Plain,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        assert_eq!(config2.level, "debug");

        let config3 = LoggingConfig {
            level: "error".to_string(),
            format: LogFormat::Json,
            output: LogOutput::Console,
            file_path: None,
            console_output: true,
        };
        assert_eq!(config3.level, "error");
    }
}